<?php

/**
 * template_cache.class.php	模板解析缓存类.
 *
 * @copyright			(C) 2005-2010 战线
 * @license				
 * @lastmodify			2012-6-1
 */
final class template_cache
{
    private $content;
    private $module;
    private $template;
    /**
     *	模板解析入口	
     *	返回解析了的模板地址
     */
    public function template_init($FileTpl, $FileHtml, $ModuleName = '', $TemplateName = '')
    {
        $this->module = $ModuleName;
        $this->template = $TemplateName;
        $this->content = file_get_contents($FileHtml);
        $this->template_parse();
        if (gettype(file_put_contents($FileTpl, $this->content)) != 'integer') {
            return false;
        }

        return true;
    }

    private function template_parse()
    {
        $stag = base64_decode('d2M=');
        $etag = base64_decode('ZW5k');
        $foreach = base64_decode('bG9vcA==');
        $this->content = preg_replace('/<\\?php(.*)/i', '&lt;?php\\1', $this->content);
        $this->content = preg_replace('/<\\?=(.*)\\?>/is', '&lt;?=\\1&gt;', $this->content);
        $this->content = preg_replace("/<script\s+language\s*=\s*php\s*>/is", '<script>', $this->content);
        $this->content = preg_replace("/<script\s+language\s*=\s*[\'|\"]php\s*[\'|\"]\s*>/is", '<script>', $this->content);

        $this->content = preg_replace("/\{$stag:templates\s+(.+)\}/", '<?php include templates(\\1);?>', $this->content);
        $this->content = preg_replace("/\{$stag:if\s+(.+?)\}/", '<?php if(\\1): ?>', $this->content);
        $this->content = preg_replace("/\{$stag:else\}/", '<?php  else: ?>', $this->content);
        $this->content = preg_replace("/\{$stag:elseif\s+(.+?)\}/", '<?php elseif (\\1): ?>', $this->content);
        $this->content = preg_replace("/\{$stag:if:$etag\}/", '<?php endif; ?>', $this->content);

        //page分页
        $this->content = preg_replace("/\{$stag:page:(\w+)\}/", "<?php echo \$page->show('\\1'); ?>", $this->content);
        $this->content = preg_replace("/\{$stag:page:\\$(\w+)\}/", '<?php echo $page->\\1; ?>', $this->content);

        $this->content = preg_replace("/\{$stag:$foreach\s+(\S+)\s+(\S+)\}/",
                                        '<?php $ln=1;if(is_array(\\1)) foreach(\\1 AS \\2): ?>', $this->content);
        $this->content = preg_replace("/\{$stag:$foreach\s+(\S+)\s+(\S+)\s+(\S+)\}/",
                                        '<?php $ln=1; if(is_array(\\1)) foreach(\\1 AS \\2 => \\3): ?>', $this->content);
        $this->content = preg_replace("/\{$stag:$foreach:$etag\}/", '<?php  endforeach; $ln++; unset($ln); ?>', $this->content);

        $this->content = preg_replace("/\{$stag:fun:([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff:]*\(([^{}]*)\))\}/",
                                        '<?php echo \\1; ?>', $this->content);

        //变量标签

        $this->content = preg_replace("/\{$stag:(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/",
                                        '<?php echo \\1; ?>', $this->content);
        $this->content = preg_replace("/\{$stag:(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\s*([\+\-\*\/])\s*(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/",
                                        '<?php echo \\1\\2\\3; ?>', $this->content);
        $this->content = preg_replace("/\{$stag:(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)([\$a-zA-Z_0-9\[\]\'\"\$\x7f-\xff]+)\}/es",
                                        "\$this->addquote('<?php echo \\1\\2; ?>')", $this->content);
        $this->content = preg_replace("/\{$stag:([a-zA-Z_0-9\[\]\'\"\$\x7f-\xff\+\-\*\/]+)\}/es",
                                        "\$this->addquote('<?php echo \\1; ?>')", $this->content);

        $this->content = preg_replace("/\{$stag:(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)--\}/",
                                        '<?php echo \\1--; ?>', $this->content);
        $this->content = preg_replace("/\{$stag:(\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)++\}/",
                                        '<?php echo \\1++; ?>', $this->content);

        $this->content = preg_replace("/\{$stag:php:start\}/", '<?php ', $this->content);
        $this->content = preg_replace("/\{$stag:php:$etag\}/", ' ?>', $this->content);

        //全局变量标签
        $this->content = preg_replace("/\{([A-Z_\x7f-\xff][A-Z0-9_\x7f-\xff]*)\}/s", '<?php echo \\1; ?>', $this->content);

        //保留标签标签
        $this->content = preg_replace("/\{$stag:(\w+)\s+([^}]+)\}/ie", "self::pc_tag_html('$1','$2', '$0')", $this->content);
        $this->content = preg_replace("/\{$stag:(\w+):$etag\}/ie", "self::end_html_tag('$1','$0')", $this->content);

        //模块调用标签		
        $this->content = preg_replace("/\{$stag:m=(\w+) mod=[\"|\'](\w+)[\"|\']([^}]+)\}/ie", "self::pc_module_tag('$1','$2', '$3')", $this->content);
        $this->content = preg_replace("/\{$stag:m=(\w+):$etag\}/ie", "self::end_module_tag('$1','$0')", $this->content);
        $this->content = '<?php defined(\'G_IN_SYSTEM\')or exit(\'No permission resources.\'); ?>'.$this->content;
    }

    private static function pc_module_tag($op, $data, $htmls)
    {
        preg_match_all("/[\"|\'](.*)[\"|\']/i", stripslashes($htmls), $matches, PREG_SET_ORDER);
        $htmls = $matches[0][0];
        $htmls = str_ireplace(' ', '', $htmls);
        $htmls = trim($htmls, ',');
        preg_match_all("/return:(\w+)[\"|\']/i", $htmls, $return, PREG_SET_ORDER);
        if (isset($return[0][1])) {
            $return = '$'.$return[0][1];
        } else {
            $return = '$data';
        }
        $html = <<<HTML
			<?php \$get_$op = System::load_app_model('get_$op','$op');$return = \$get_$op->$data($htmls); ?>	
HTML;

        return $html;
    }

    private static function end_module_tag($op, $htmls)
    {
        $op = trim($op);

        return '';
    }

    /**
     * 解析系统保留标签.
     *
     * @param string $op   操作方式
     * @param string $data 参数
     * @param string $html 匹配到的所有的HTML代码
     */
    private static function pc_tag_html($op, $data, $htmls)
    {
        static $display = array('get' => false, 'page' => false);
        $oparr = array('getpage', 'getlist', 'getcount', 'getone', 'htmlcache', 'block');
        $modarr = array('sql', 'cache', 'mod', 'name', 'return', 'num', 'page', 'type', 'pageurl', 'key', 'func');
        $datas = array();
        $op = trim($op);
        $html = '';

        preg_match_all("/([a-z]+)\=[\"]?([^\"]+)[\"]?/i", stripslashes($data), $matches, PREG_SET_ORDER);

        foreach ($matches as $v) {
            $datas[$v[1]] = $v[2];
            if (in_array($v[1], $modarr)) {
                $$v[1] = $v[2];
                continue;
            }
        }

        $datas['mod'] = $mod = isset($mod) && trim($mod) ? trim($mod) : 'get';
        $datas['sql'] = $sql = isset($sql) && trim($sql) ? trim($sql) : '';
        $datas['num'] = $num = isset($num) ? intval($num) : 20;
        if ($num <= 0) {
            $datas['num'] = $num = 20;
        }

        //$datas['page']=$page=isset($page) ? $page : '$_GET[\'p\']';			
        //$datas['pageurl']=$pageurl=isset($pageurl) ? $pageurl : 0;

        $datas['page'] = $page = '$_GET[\'p\']';
        $datas['pageurl'] = $pageurl = 0;
        $datas['key'] = $key = isset($key) ? trim($key) : "''";

        $datas['cache'] = $cache = isset($cache) && intval($cache) ? intval($cache) : 0;
        $datas['return'] = $return = isset($return) && trim($return) ? trim($return) : 'data';
        $datas['name'] = $name = isset($name) && trim($name) ? trim($name) : 0;
        $datas['type'] = $type = isset($type) ? trim($type) : 1;

        if (!in_array($type, array('MYSQL_ASSOC', 'MYSQL_NUM', 'MYSQL_BOTH'))) {
            $type = 1;
        }
        if (!in_array($op, $oparr)) {
            return stripslashes($htmls);
        }
        switch ($op) {
            case 'getlist':
                if (empty($sql)) {
                    return stripslashes($htmls);
                }
                $html .= '<?php '.'$'.$return.'='.'$this->DB()->GetList("'.$sql.'",array("type"=>'.$type.',"key"=>'.$key.',"cache"=>'.$cache.')); ?>';
                break;
            case 'getpage':
                if (empty($sql)) {
                    return stripslashes($htmls);
                }
                $html .= '<?php $num='.$num.';$total=$this->DB()->GetCount("'.$sql.'"); ?>';
                $html .= '<?php $page=System::load_sys_class(\'page\');if(isset('.$page.')){$pagenum='.$page.';}else{$pagenum=1;} $page->config($total,$num,$pagenum,"'.$pageurl.'"); ?>';
                $html .= '<?php '.'$'.$return.'='.'$this->DB()->GetPage("'.$sql.'",array("num"=>$num,"page"=>$pagenum,"type"=>'.$type.',"key"=>'.$key.',"cache"=>'.$cache.')); ?>';
                break;
            case 'getone':
                if (empty($sql)) {
                    return stripslashes($htmls);
                }
                $html .= '<?php $mysql_model=System::load_sys_class(\'model\'); ?>';
                $html .= '<?php '.'$'.$return.'='.'$this->DB()->GetOne("'.$sql.'",array("cache"=>'.$cache.')); ?>';
            break;
        }

        return $html;
    }
    private static function end_html_tag($op, $htmls)
    {
        $op = trim($op);
        $oparr = array('getpage', 'getlist', 'getcount', 'getone', 'htmlcache', 'block');
        if (!in_array($op, $oparr)) {
            return stripslashes($htmls);
        }

        return '<?php if(defined(\'G_IN_ADMIN\')) {echo \'<div style="padding:8px;background-color:#F93; color:#fff;border:1px solid #f60;text-align:center"><b>This Tag</b></div>\';}?>';
    }

    /**
     * 解析PC标签.
     *
     * @param string $op   操作方式
     * @param string $data 参数
     * @param string $html 匹配到的所有的HTML代码
     */
    private static function pc_tag($op, $data, $html)
    {
        static $display = array('op' => false, 'page' => false);
        $datas = array();
        $html = '';
        $modarr = array('mod', 'sql', 'page', 'cache', 'return', 'one');
        preg_match_all("/([a-z]+)\=[\"]?([^\"]+)[\"]?/i", stripslashes($data), $matches, PREG_SET_ORDER);
        foreach ($matches as $v) {
            $datas[$v[1]] = $v[2];
            if (in_array($v[1], $modarr)) {
                $$v[1] = $v[2];
                continue;
            }
        }

        $CacheTime = System::load_sys_config('system', 'cache');
        $datas['mod'] = $mod = isset($mod) && trim($mod) ? trim($mod) : 'get';
        $datas['sql'] = $sql = isset($sql) && trim($sql) ? trim($sql) : '';
        $datas['page'] = $page = isset($page) ? true : false;
        $datas['cache'] = $cache = isset($cache) && intval($cache) ? intval($cache) : intval($CacheTime);
        $datas['return'] = $return = isset($return) && trim($return) ? trim($return) : 'data';
        $datas['one'] = $one = isset($one) && trim($one) ? true : false;

        if (!file_exists(G_SYSTEM.'model'.
                       DIRECTORY_SEPARATOR.$op.'_tag.class.php')) {
            exit('Model File Error:'.' File Not Found');
        }

        if (($page) && !($display['page'])) {
            $display['page'] = true;
            $html .= '<?php $page=System::load_sys_class("page"); ?>';
        }
        $html .= '<?php ';
        if (($op) && !($display['op'])) {
            $display['op'] = true;
            $html .= '$'.$op.'_tag';
            $html .= '=System::load_app_model("'.$op.'_tag");';
        }
        if ($op) {
            $html .= 'if(method_exists($'.$op.'_tag,"'.$mod.'")){';
            $html .= '$'.$return.'=$'.$op.'_tag->'.$mod.'('.self::arr_to_html($datas).');} ?>';
        }

        return $html;
    }

    /**
     * PC标签结束
     */
    private static function end_pc_tag()
    {
        return '<?php if(defined(\'G_IN_ADMIN\')) {echo \'<div style="padding:8px;background-color:#F93; color:#fff;border:1px solid #f60;text-align:center"><b>This Tag</b></div>\';}?>';
    }
    /**
     * 转义 // 为 /.
     *
     * @param $var	转义的字符
     *
     * @return 转义后的字符
     */
    public function addquote($var)
    {
        return str_replace('\\"', '"', preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
    }

    /**
     * 转换数据为HTML代码
     *
     * @param array $data 数组
     */
    private static function arr_to_html($data)
    {
        if (is_array($data)) {
            $str = 'array(';
            foreach ($data as $key => $val) {
                if (is_array($val)) {
                    $str .= "'$key'=>".self::arr_to_html($val).',';
                } else {
                    if (strpos($val, '$') === 0) {
                        $str .= "'$key'=>$val,";
                    } else {
                        if ($key == 'sql') {
                            $str .= "'$key'=>".'"'.$val.'",';
                        } else {
                            $str .= "'$key'=>'".new_addslashes($val)."',";
                        }
                    }
                }
            }

            return $str.')';
        }

        return false;
    }
}
